﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.IO;
using OOAD_Project_Engine.Foundation;

namespace OOAD_Project_Engine.Application.Services
{
    public sealed class ContentProvider : GameComponent, IContentService
    {
        ContentManager content;
        Dictionary<string, Texture2D> localTextureFiles;

        public ContentProvider(Game game)
            : base(game)
        {
            Game.Components.ComponentAdded += this.OnComponentAdded;
            Game.Components.ComponentRemoved += this.OnComponentRemoved;
            localTextureFiles = new Dictionary<string, Texture2D>();
            content = game.Content;
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.Game.Services.GetService(typeof(IContentService)) == this)
                {
                    this.Game.Services.RemoveService(typeof(IContentService));
                }
            }

            base.Dispose(disposing);
        }

        #region IContentManagerService Members

        public T Load<T>(string assetName)
        {
            return content.Load<T>(assetName);
        }


        public T LoadFromFile<T>(string filePath)
        {
            if (typeof(T).IsAssignableFrom(typeof(Texture2D)))
                return (T)Convert.ChangeType(LoadLocalTextureFile(filePath), typeof(T)); ;

            throw new Exception();
        }

        private Texture2D LoadLocalTextureFile(string filePath)
        {
            if (localTextureFiles.ContainsKey(filePath))
            {
                return localTextureFiles[filePath];
            }
            else
            {
                FileStream stream = new FileStream(@filePath, FileMode.Open);
                GraphicsDevice graphic = GameHelper.GetService<IGraphicService>().GraphicsDevice;
                Texture2D tex = Texture2D.FromStream(graphic, stream);
                stream.Close();
                localTextureFiles.Add(filePath, tex);
                return tex;
            }
        }


        public void Unload()
        {
            content.Unload();
        }

        public ContentManager ContentManager
        {
            get
            {
                return content;
            }
        }

        #endregion

        public void OnComponentAdded(object sender, GameComponentCollectionEventArgs e)
        {
            if (e.GameComponent == this)
            {
                if (Game.Services.GetService(typeof(IContentService)) != null)
                {
                    throw new ArgumentException("ContentManager already present.");
                }
                Game.Services.AddService(typeof(IContentService), this);
            }
        }

        public void OnComponentRemoved(object sender, GameComponentCollectionEventArgs e)
        {
            if (e.GameComponent == this)
            {
                Game.Services.RemoveService(typeof(IContentService));
                Game.Components.ComponentAdded -= this.OnComponentAdded;
                Game.Components.ComponentRemoved -= this.OnComponentRemoved;
            }
        }
    }

}
